// ==========================================================================
// Dedmonwakeen's Raid DPS/TPS Simulator.
// Send questions to natehieter@gmail.com
// ==========================================================================

#include "simulationcraft.h"

namespace { // ANONYMOUS NAMESPACE ==========================================


// print_html_contents ======================================================

static void print_html_contents( FILE*  file, sim_t* sim )
{
  size_t c = 2;     // total number of TOC entries
  if ( sim -> scaling -> has_scale_factors() )
    ++c;

  const int num_players = ( int ) sim -> players_by_name.size();
  c += num_players;
  if ( sim -> report_targets )
    c += sim -> targets_by_name.size();

  if ( sim -> report_pets_separately )
  {
    for ( int i=0; i < num_players; i++ )
    {
      for ( pet_t* pet = sim -> players_by_name[ i ] -> pet_list; pet; pet = pet -> next_pet )
      {
        if ( pet -> summoned )
          ++c;
      }
    }
  }

  fputs( "\t\t<div id=\"table-of-contents\" class=\"section grouped-first grouped-last\">\n"
         "\t\t\t<h2 class=\"toggle\">Table of Contents</h2>\n"
         "\t\t\t<div class=\"toggle-content hide\">\n", file );

  // set number of columns
  int n;         // number of columns
  const char* toc_class; // css class
  if ( c < 6 )
  {
    n = 1;
    toc_class = "toc-wide";
  }
  else if ( sim -> report_pets_separately )
  {
    n = 2;
    toc_class = "toc-wide";
  }
  else if ( c < 9 )
  {
    n = 2;
    toc_class = "toc-narrow";
  }
  else
  {
    n = 3;
    toc_class = "toc-narrow";
  }

  int pi = 0;    // player counter
  int ab = 0;    // auras and debuffs link added yet?
  for ( int i=0; i < n; i++ )
  {
    int cs;    // column size
    if ( i == 0 )
    {
      cs = ( int ) ceil( 1.0 * c / n );
    }
    else if ( i == 1 )
    {
      if ( n == 2 )
      {
        cs = ( int ) ( c - ceil( 1.0 * c / n ) );
      }
      else
      {
        cs = ( int ) ceil( 1.0 * c / n );
      }
    }
    else
    {
      cs = ( int ) ( c - 2 * ceil( 1.0 * c / n ) );
    }

    fprintf( file,
             "\t\t\t\t<ul class=\"toc %s\">\n",
             toc_class );

    int ci = 1;    // in-column counter
    if ( i == 0 )
    {
      fputs( "\t\t\t\t\t<li><a href=\"#raid-summary\">Raid Summary</a></li>\n", file );
      ci++;
      if ( sim -> scaling -> has_scale_factors() )
      {
        fputs( "\t\t\t\t\t<li><a href=\"#raid-scale-factors\">Scale Factors</a></li>\n", file );
        ci++;
      }
    }
    while ( ci <= cs )
    {
      if ( pi < ( int ) sim -> players_by_name.size() )
      {
        player_t* p = sim -> players_by_name[ pi ];
        fprintf( file,
                 "\t\t\t\t\t<li><a href=\"#%s\">%s</a>",
                 p -> name(), p -> name() );
        ci++;
        if ( sim -> report_pets_separately )
        {
          fputs( "\n\t\t\t\t\t\t<ul>\n", file );
          for ( pet_t* pet = sim -> players_by_name[ pi ] -> pet_list; pet; pet = pet -> next_pet )
          {
            if ( pet -> summoned )
            {
              fprintf( file,
                       "\t\t\t\t\t\t\t<li><a href=\"#%s\">%s</a></li>\n",
                       pet -> name(), pet -> name() );
              ci++;
            }
          }
          fputs( "\t\t\t\t\t\t</ul>", file );
        }
        fputs( "</li>\n", file );
        pi++;
      }
      if ( pi == ( int ) sim -> players_by_name.size() )
      {
        if ( ab == 0 )
        {
          fputs( "\t\t\t\t\t\t<li><a href=\"#auras-buffs\">Auras/Buffs</a></li>\n", file );
          ab = 1;
        }
        ci++;
        fputs( "\t\t\t\t\t\t<li><a href=\"#sim-info\">Simulation Information</a></li>\n", file );
        ci++;
      }
      if ( sim -> report_targets && ab > 0 )
      {
        if ( ab == 1 )
        {
          pi = 0;
          ab = 2;
        }
        while ( ci <= cs )
        {
          if ( pi < ( int ) sim -> targets_by_name.size() )
          {
            player_t* p = sim -> targets_by_name[ pi ];
            fprintf( file,
                     "\t\t\t\t\t<li><a href=\"#%s\">%s</a></li>\n",
                     p -> name(), p -> name() );
          }
          ci++;
          pi++;
        }
      }
    }
    fputs( "\t\t\t\t</ul>\n", file );
  }

  fputs( "\t\t\t\t<div class=\"clear\"></div>\n"
         "\t\t\t</div>\n\n"
         "\t\t</div>\n\n", file );
}



// print_html_sim_summary ===================================================

static void print_html_sim_summary( FILE*  file, sim_t* sim )
{

  fprintf( file,
           "\t\t\t\t<div id=\"sim-info\" class=\"section\">\n" );

  fprintf( file,
           "\t\t\t\t\t<h2 class=\"toggle\">Simulation & Raid Information</h2>\n"
           "\t\t\t\t\t\t<div class=\"toggle-content hide\">\n" );

  fprintf( file,
           "\t\t\t\t\t\t<table class=\"sc mt\">\n" );

  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Iterations:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%d</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> iterations );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Threads:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%d</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> threads < 1 ? 1 : sim -> threads );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Confidence:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.2f%%</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> confidence * 100.0 );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Fight Length:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.0f - %.0f ( %.1f )</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> simulation_length.min,
           sim -> simulation_length.max,
           sim -> simulation_length.mean );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th><h2>Performance:</h2></th>\n"
           "\t\t\t\t\t\t\t\t<td></td>\n"
           "\t\t\t\t\t\t\t</tr>\n" );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Total Events Processed:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%ld</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           ( long ) sim -> total_events_processed );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Max Event Queue:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%ld</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           ( long ) sim -> max_events_remaining );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Sim Seconds:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.0f</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> iterations * sim -> simulation_length.mean );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>CPU Seconds:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.4f</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> elapsed_cpu.total_seconds() );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Speed Up:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.0f</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           sim -> iterations * sim -> simulation_length.mean / sim -> elapsed_cpu.total_seconds() );

  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th><h2>Settings:</h2></th>\n"
           "\t\t\t\t\t\t\t\t<td></td>\n"
           "\t\t\t\t\t\t\t</tr>\n" );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>World Lag:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.0f ms ( stddev = %.0f ms )</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           ( double )sim -> world_lag.total_millis(), ( double )sim -> world_lag_stddev.total_millis() );
  fprintf( file,
           "\t\t\t\t\t\t\t<tr class=\"left\">\n"
           "\t\t\t\t\t\t\t\t<th>Queue Lag:</th>\n"
           "\t\t\t\t\t\t\t\t<td>%.0f ms ( stddev = %.0f ms )</td>\n"
           "\t\t\t\t\t\t\t</tr>\n",
           ( double )sim -> queue_lag.total_millis(), ( double )sim -> queue_lag_stddev.total_millis() );
  if ( sim -> strict_gcd_queue )
  {
    fprintf( file,
             "\t\t\t\t\t\t\t<tr class=\"left\">\n"
             "\t\t\t\t\t\t\t\t<th>GCD Lag:</th>\n"
             "\t\t\t\t\t\t\t\t<td>%.0f ms ( stddev = %.0f ms )</td>\n"
             "\t\t\t\t\t\t\t</tr>\n",
             ( double )sim -> gcd_lag.total_millis(), ( double )sim -> gcd_lag_stddev.total_millis() );
    fprintf( file,
             "\t\t\t\t\t\t\t<tr class=\"left\">\n"
             "\t\t\t\t\t\t\t\t<th>Channel Lag:</th>\n"
             "\t\t\t\t\t\t\t\t<td>%.0f ms ( stddev = %.0f ms )</td>\n"
             "\t\t\t\t\t\t\t</tr>\n",
             ( double )sim -> channel_lag.total_millis(), ( double )sim -> channel_lag_stddev.total_millis() );
    fprintf( file,
             "\t\t\t\t\t\t\t<tr class=\"left\">\n"
             "\t\t\t\t\t\t\t\t<th>Queue GCD Reduction:</th>\n"
             "\t\t\t\t\t\t\t\t<td>%.0f ms</td>\n"
             "\t\t\t\t\t\t\t</tr>\n",
             ( double )sim -> queue_gcd_reduction.total_millis() );
  }


  fprintf( file,
           "\t\t\t\t\t\t</table>\n" );

  // Left side charts: dps, gear, timeline, raid events

  fprintf( file,
           "\t\t\t\t<div class=\"charts charts-left\">\n" );
  // Timeline Distribution Chart
  if ( sim -> iterations > 1 && ! sim -> timeline_chart.empty() )
  {
    fprintf( file,
             "\t\t\t\t\t<a href=\"#help-timeline-distribution\" class=\"help\"><img src=\"%s\" alt=\"Timeline Distribution Chart\" /></a>\n",
             sim -> timeline_chart.c_str() );
  }
  // Gear Charts
  int count = ( int ) sim -> gear_charts.size();
  for ( int i=0; i < count; i++ )
  {
    fprintf( file,
             "\t\t\t\t\t<img src=\"%s\" alt=\"Gear Chart\" />\n",
             sim -> gear_charts[ i ].c_str() );
  }
  // Raid Downtime Chart
  if ( ! sim -> downtime_chart.empty() )
  {
    fprintf( file,
             "\t\t\t\t\t<img src=\"%s\" alt=\"Player Downtime Chart\" />\n",
             sim -> downtime_chart.c_str() );
  }

  fprintf( file,
           "\t\t\t\t</div>\n" );

  // Right side charts: dpet
  fprintf( file,
           "\t\t\t\t<div class=\"charts\">\n" );
  count = ( int ) sim -> dpet_charts.size();
  for ( int i=0; i < count; i++ )
  {
    fprintf( file,
             "\t\t\t\t\t<img src=\"%s\" alt=\"DPET Chart\" />\n",
             sim -> dpet_charts[ i ].c_str() );
  }



  fprintf( file,
           "\t\t\t\t</div>\n" );


  // closure
  fprintf( file,
           "\t\t\t\t<div class=\"clear\"></div>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n\n" );
}

// print_html_raid_summary ==================================================

static void print_html_raid_summary( FILE*  file, sim_t* sim )
{
  fprintf( file,
           "\t\t<div id=\"raid-summary\" class=\"section section-open\">\n\n" );
  fprintf( file,
           "\t\t\t<h2 class=\"toggle open\">Raid Summary</h2>\n" );
  fprintf( file,
           "\t\t\t<div class=\"toggle-content\">\n" );
  fprintf( file,
           "\t\t\t<ul class=\"params\">\n" );
  fprintf( file,
           "\t\t\t\t<li><b>Raid Damage:</b> %.0f</li>\n",
           sim -> total_dmg.mean );
  fprintf( file,
           "\t\t\t\t<li><b>Raid DPS:</b> %.0f</li>\n",
           sim -> raid_dps.mean );
  if ( sim -> total_heal.mean > 0 )
  {
    fprintf( file,
             "\t\t\t\t<li><b>Raid Heal:</b> %.0f</li>\n",
             sim -> total_heal.mean );
    fprintf( file,
             "\t\t\t\t<li><b>Raid HPS:</b> %.0f</li>\n",
             sim -> raid_hps.mean );
  }
  fprintf( file,
           "\t\t\t</ul><p>&nbsp;</p>\n" );

  // Left side charts: dps, raid events
  fprintf( file,
           "\t\t\t\t<div class=\"charts charts-left\">\n" );
  int count = ( int ) sim -> dps_charts.size();
  for ( int i=0; i < count; i++ )
  {
    fprintf( file, "\t\t\t\t\t<map id='DPSMAP%d' name='DPSMAP%d'></map>\n", i, i );
    fprintf( file,
             "\t\t\t\t\t<img id='DPSIMG%d' src=\"%s\" alt=\"DPS Chart\" />\n",
             i, sim -> dps_charts[ i ].c_str() );
  }

  if ( ! sim -> raid_events_str.empty() )
  {
    fprintf( file,
             "\t\t\t\t\t<table>\n"
             "\t\t\t\t\t\t<tr>\n"
             "\t\t\t\t\t\t\t<th></th>\n"
             "\t\t\t\t\t\t\t<th class=\"left\">Raid Event List</th>\n"
             "\t\t\t\t\t\t</tr>\n" );
    std::vector<std::string> raid_event_names;
    int num_raid_events = util_t::string_split( raid_event_names, sim -> raid_events_str, "/" );
    for ( int i=0; i < num_raid_events; i++ )
    {
      fprintf( file,
               "\t\t\t\t\t\t<tr" );
      if ( ( i & 1 ) )
      {
        fprintf( file, " class=\"odd\"" );
      }
      fprintf( file, ">\n" );
      fprintf( file,
               "\t\t\t\t\t\t\t<th class=\"right\">%d</th>\n"
               "\t\t\t\t\t\t\t<td class=\"left\">%s</td>\n"
               "\t\t\t\t\t\t</tr>\n",
               i,
               raid_event_names[ i ].c_str() );
    }
    fprintf( file,
             "\t\t\t\t\t</table>\n" );
  }
  fprintf( file,
           "\t\t\t\t</div>\n" );

  // Right side charts: hps
  fprintf( file,
           "\t\t\t\t<div class=\"charts\">\n" );

  count = ( int ) sim -> hps_charts.size();
  for ( int i=0; i < count; i++ )
  {
    fprintf( file, "\t\t\t\t\t<map id='HPSMAP%d' name='HPSMAP%d'></map>\n", i, i );
    fprintf( file,
             "\t\t\t\t\t<img id='HPSIMG%d' src=\"%s\" alt=\"HPS Chart\" />\n",
             i, sim -> hps_charts[ i ].c_str() );
  }
  // RNG chart
  if ( sim -> report_rng )
  {
    fprintf( file,
             "\t\t\t\t\t<ul>\n" );
    for ( int i=0; i < ( int ) sim -> players_by_name.size(); i++ )
    {
      player_t* p = sim -> players_by_name[ i ];
      double range = ( p -> dps.percentile( 0.95 ) - p -> dps.percentile( 0.05 ) ) / 2.0;
      fprintf( file,
               "\t\t\t\t\t\t<li>%s: %.1f / %.1f%%</li>\n",
               p -> name(),
               range,
               p -> dps.mean ? ( range * 100 / p -> dps.mean ) : 0 );
    }
    fprintf( file,
             "\t\t\t\t\t</ul>\n" );
  }

  fprintf( file,
           "\t\t\t\t</div>\n" );

  // closure
  fprintf( file,
           "\t\t\t\t<div class=\"clear\"></div>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n\n" );

}

// print_html_raid_imagemaps ==================================================

static void print_html_raid_imagemap( FILE* file, sim_t* sim, int num, bool dps )
{
  std::vector<player_t*> player_list = ( dps ) ? sim -> players_by_dps : sim -> players_by_hps;
  int start = num * MAX_PLAYERS_PER_CHART;
  unsigned int end = start + MAX_PLAYERS_PER_CHART;

  for ( unsigned int i=0; i < player_list.size(); i++ )
  {
    player_t* p = player_list[ i ];
    if ( dps ? p -> dps.mean <= 0 : p -> hps.mean <=0 )
    {
      player_list.resize( i );
      break;
    }
  }

  if ( end > player_list.size() ) end = static_cast<unsigned>( player_list.size() );

  fprintf( file, "\t\t\tn = [" );
  for ( int i=end-1; i >= start; i-- )
  {
    fprintf( file, "\"%s\"", player_list[i] -> name_str.c_str() );
    if ( i != start ) fprintf( file, ", " );
  }
  fprintf( file, "];\n" );

  char imgid[32];
  util_t::snprintf( imgid, sizeof( imgid ), "%sIMG%d", ( dps ) ? "DPS" : "HPS", num );
  char mapid[32];
  util_t::snprintf( mapid, sizeof( mapid ), "%sMAP%d", ( dps ) ? "DPS" : "HPS", num );

  fprintf( file,
           "\t\t\tu = document.getElementById('%s').src;\n"
           "\t\t\tgetMap(u, n, function(mapStr) {\n"
           "\t\t\t\tdocument.getElementById('%s').innerHTML += mapStr;\n"
           "\t\t\t\t$j('#%s').attr('usemap','#%s');\n"
           "\t\t\t\t$j('#%s area').click(function(e) {\n"
           "\t\t\t\t\tanchor = $j(this).attr('href');\n"
           "\t\t\t\t\ttarget = $j(anchor).children('h2:first');\n"
           "\t\t\t\t\topen_anchor(target);\n"
           "\t\t\t\t});\n"
           "\t\t\t});\n\n",
           imgid, mapid, imgid, mapid, mapid );
}

static void print_html_raid_imagemaps( FILE*  file, sim_t* sim )
{

  fprintf( file,
           "\t\t<script type=\"text/javascript\">\n"
           "\t\t\tvar $j = jQuery.noConflict();\n"
           "\t\t\tfunction getMap(url, names, mapWrite) {\n"
           "\t\t\t\t$j.getJSON(url + '&chof=json&callback=?', function(jsonObj) {\n"
           "\t\t\t\t\tvar area = false;\n"
           "\t\t\t\t\tvar chart = jsonObj.chartshape;\n"
           "\t\t\t\t\tvar mapStr = '';\n"
           "\t\t\t\t\tfor (var i = 0; i < chart.length; i++) {\n"
           "\t\t\t\t\t\tarea = chart[i];\n"
           "\t\t\t\t\t\tarea.coords[2] = 523;\n"
           "\t\t\t\t\t\tmapStr += \"\\n  <area name='\" + area.name + \"' shape='\" + area.type + \"' coords='\" + area.coords.join(\",\") + \"' href='#\" + names[i] + \"'  title='\" + names[i] + \"'>\";\n"
           "\t\t\t\t\t}\n"
           "\t\t\t\t\tmapWrite(mapStr);\n"
           "\t\t\t\t});\n"
           "\t\t\t}\n\n" );

  int count = ( int ) sim -> dps_charts.size();
  for ( int i=0; i < count; i++ )
  {
    print_html_raid_imagemap( file, sim, i, true );
  }

  count = ( int ) sim -> hps_charts.size();
  for ( int i=0; i < count; i++ )
  {
    print_html_raid_imagemap( file, sim, i, false );
  }

  fprintf( file, "\t\t</script>\n" );

}

// print_html_scale_factors =================================================

static void print_html_scale_factors( FILE*  file, sim_t* sim )
{
  if ( ! sim -> scaling -> has_scale_factors() ) return;

  if ( sim -> report_precision < 0 )
    sim -> report_precision = 2;

  fprintf( file,
           "\t\t<div id=\"raid-scale-factors\" class=\"section grouped-first\">\n\n"
           "\t\t\t<h2 class=\"toggle\">DPS Scale Factors (dps increase per unit stat)</h2>\n"
           "\t\t\t<div class=\"toggle-content hide\">\n" );

  fprintf( file,
           "\t\t\t\t<table class=\"sc\">\n" );

  std::string buffer;
  int num_players = ( int ) sim -> players_by_name.size();
  int prev_type = PLAYER_NONE;

  for ( int i=0; i < num_players; i++ )
  {
    player_t* p = sim -> players_by_name[ i ];

    if ( p -> type != prev_type )
    {
      prev_type = p -> type;

      fprintf( file,
               "\t\t\t\t\t<tr>\n"
               "\t\t\t\t\t\t<th class=\"left small\">Profile</th>\n" );
      for ( int j=0; j < STAT_MAX; j++ )
      {
        if ( sim -> scaling -> stats.get_stat( j ) != 0 )
        {
          fprintf( file,
                   "\t\t\t\t\t\t<th class=\"small\">%s</th>\n",
                   util_t::stat_type_abbrev( j ) );
        }
      }
      fprintf( file,
               "\t\t\t\t\t\t<th class=\"small\">wowhead</th>\n"
               "\t\t\t\t\t\t<th class=\"small\">lootrank</th>\n"
               "\t\t\t\t\t</tr>\n" );
    }

    fprintf( file,
             "\t\t\t\t\t<tr" );
    if ( ( i & 1 ) )
    {
      fprintf( file, " class=\"odd\"" );
    }
    fprintf( file, ">\n" );
    fprintf( file,
             "\t\t\t\t\t\t<td class=\"left small\">%s</td>\n",
             p -> name() );
    for ( int j=0; j < STAT_MAX; j++ )
    {
      if ( sim -> scaling -> stats.get_stat( j ) != 0 )
      {
        if ( p -> scaling.get_stat( j ) == 0 )
        {
          fprintf( file, "\t\t\t\t\t\t<td class=\"small\">-</td>\n" );
        }
        else
        {
          fprintf( file,
                   "\t\t\t\t\t\t<td class=\"small\">%.*f</td>\n",
                   sim -> report_precision,
                   p -> scaling.get_stat( j ) );
        }
      }
    }
    fprintf( file,
             "\t\t\t\t\t\t<td class=\"small\"><a href=\"%s\"> wowhead </a></td>\n"
             "\t\t\t\t\t\t<td class=\"small\"><a href=\"%s\"> lootrank</a></td>\n"
             "\t\t\t\t\t</tr>\n",
             p -> gear_weights_wowhead_link.c_str(),
             p -> gear_weights_lootrank_link.c_str() );
  }
  fprintf( file,
           "\t\t\t\t</table>\n" );
  if ( sim -> iterations < 10000 )
    fprintf( file,
             "\t\t\t\t<div class=\"alert\">\n"
             "\t\t\t\t\t<h3>Warning</h3>\n"
             "\t\t\t\t\t<p>Scale Factors generated using less than 10,000 iterations will vary from run to run.</p>\n"
             "\t\t\t\t</div>\n" );
  fprintf( file,
           "\t\t\t</div>\n"
           "\t\t</div>\n\n" );
}

// print_html_help_boxes ====================================================

static void print_html_help_boxes( FILE*  file, sim_t* sim )
{
  fprintf( file,
           "\t\t<!-- Help Boxes -->\n" );

  fprintf( file,
           "\t\t<div id=\"help-apm\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>APM</h3>\n"
           "\t\t\t\t<p>Average number of actions executed per minute.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-constant-buffs\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Constant Buffs</h3>\n"
           "\t\t\t\t<p>Buffs received prior to combat and present the entire fight.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-count\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Count</h3>\n"
           "\t\t\t\t<p>Average number of times an action is executed per iteration.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-crit\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Crit</h3>\n"
           "\t\t\t\t<p>Average crit damage.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-crit-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Crit%%</h3>\n"
           "\t\t\t\t<p>Percentage of executes that resulted in critical strikes.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dodge-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Dodge%%</h3>\n"
           "\t\t\t\t<p>Percentage of executes that resulted in dodges.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dpe\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>DPE</h3>\n"
           "\t\t\t\t<p>Average damage per execution of an individual action.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dpet\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>DPET</h3>\n"
           "\t\t\t\t<p>Average damage per execute time of an individual action; the amount of damage generated, divided by the time taken to execute the action, including time spent in the GCD.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dpr\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>DPR</h3>\n"
           "\t\t\t\t<p>Average damage per resource point spent.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dps\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>DPS</h3>\n"
           "\t\t\t\t<p>Average damage per active player duration.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dpse\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Effective DPS</h3>\n"
           "\t\t\t\t<p>Average damage per fight duration.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dps-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>DPS%%</h3>\n"
           "\t\t\t\t<p>Percentage of total DPS contributed by a particular action.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-dynamic-buffs\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Dynamic Buffs</h3>\n"
           "\t\t\t\t<p>Temporary buffs received during combat, perhaps multiple times.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-error\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Error</h3>\n"
           "\t\t\t\t<p>Estimator for the %.2f%% confidence intervall.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n",
           sim -> confidence * 100.0 );

  fprintf( file,
           "\t\t<div id=\"help-glance-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>G%%</h3>\n"
           "\t\t\t\t<p>Percentage of executes that resulted in glancing blows.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-block-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>G%%</h3>\n"
           "\t\t\t\t<p>Percentage of executes that resulted in blocking blows.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-hit\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Hit</h3>\n"
           "\t\t\t\t<p>Average non-crit damage.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-interval\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Interval</h3>\n"
           "\t\t\t\t<p>Average time between executions of a particular action.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-max\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Max</h3>\n"
           "\t\t\t\t<p>Maximum crit damage over all iterations.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-miss-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>M%%</h3>\n"
           "\t\t\t\t<p>Percentage of executes that resulted in misses, dodges or parries.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-origin\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Origin</h3>\n"
           "\t\t\t\t<p>The player profile from which the simulation script was generated. The profile must be copied into the same directory as this HTML file in order for the link to work.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-parry-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Parry%%</h3>\n"
           "\t\t\t\t<p>Percentage of executes that resulted in parries.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-range\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Range</h3>\n"
           "\t\t\t\t<p>( dps.percentile( 0.95 ) - dps.percentile( 0.05 ) / 2</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-rps-in\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>RPS In</h3>\n"
           "\t\t\t\t<p>Average resource points generated per second.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-rps-out\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>RPS Out</h3>\n"
           "\t\t\t\t<p>Average resource points consumed per second.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-scale-factors\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Scale Factors</h3>\n"
           "\t\t\t\t<p>DPS gain per unit stat increase except for <b>Hit/Expertise</b> which represent <b>DPS loss</b> per unit stat <b>decrease</b>.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-ticks\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Ticks</h3>\n"
           "\t\t\t\t<p>Average number of periodic ticks per iteration. Spells that do not have a damage-over-time component will have zero ticks.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-ticks-crit\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>T-Crit</h3>\n"
           "\t\t\t\t<p>Average crit tick damage.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-ticks-crit-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>T-Crit%%</h3>\n"
           "\t\t\t\t<p>Percentage of ticks that resulted in critical strikes.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-ticks-hit\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>T-Hit</h3>\n"
           "\t\t\t\t<p>Average non-crit tick damage.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-ticks-miss-pct\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>T-M%%</h3>\n"
           "\t\t\t\t<p>Percentage of ticks that resulted in misses, dodges or parries.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-ticks-uptime\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>UpTime%%</h3>\n"
           "\t\t\t\t<p>Percentage of total time that DoT is ticking on target.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-timeline-distribution\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Timeline Distribution</h3>\n"
           "\t\t\t\t<p>The simulated encounter's duration can vary based on the health of the target and variation in the raid DPS. This chart shows how often the duration of the encounter varied by how much time.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<div id=\"help-fight-length\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Fight Length</h3>\n"
           "\t\t\t\t<p>Fight Length: %.0f<br />\n"
           "\t\t\t\tVary Combat Length: %.2f</p>\n"
           "\t\t\t\t<p>Fight Length is the specified average fight duration. If vary_combat_length is set, the fight length will vary by +/- that portion of the value. See <a href=\"http://code.google.com/p/simulationcraft/wiki/Options#Combat_Length\" class=\"ext\">Combat Length</a> in the wiki for further details.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n",
           sim -> max_time.total_seconds(),
           sim -> vary_combat_length );

  fprintf( file,
           "\t\t<div id=\"help-waiting\">\n"
           "\t\t\t<div class=\"help-box\">\n"
           "\t\t\t\t<h3>Waiting</h3>\n"
           "\t\t\t\t<p>This is the percentage of time in which no action can be taken other than autoattacks. This can be caused by resource starvation, lockouts, and timers.</p>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n" );

  fprintf( file,
           "\t\t<!-- End Help Boxes -->\n" );
}

// print_html_styles ====================================================

static void print_html_styles( FILE*  file, sim_t* sim )
{
  // Styles
  // If file is being hosted on simulationcraft.org, link to the local
  // stylesheet; otherwise, embed the styles.
  if ( sim -> hosted_html )
  {
    fprintf( file,
             "\t\t<style type=\"text/css\" media=\"screen\">\n"
             "\t\t\t@import url('http://www.simulationcraft.org/css/styles.css');\n"
             "\t\t</style>\n"
             "\t\t<style type=\"text/css\" media=\"print\">\n"
             "\t\t  @import url('http://www.simulationcraft.org/css/styles-print.css');\n"
             "\t\t</style>\n" );
  }
  else if ( sim -> print_styles )
  {
    fprintf( file,
             "\t\t<style type=\"text/css\" media=\"all\">\n"
             "\t\t\t* {border: none;margin: 0;padding: 0; }\n"
             "\t\t\tbody {padding: 5px 25px 25px 25px;font-family: \"Lucida Grande\", Arial, sans-serif;font-size: 14px;background-color: #f9f9f9;color: #333;text-align: center; }\n"
             "\t\t\tp {margin: 1em 0 1em 0; }\n"
             "\t\t\th1, h2, h3, h4, h5, h6 {width: auto;color: #777;margin-top: 1em;margin-bottom: 0.5em; }\n"
             "\t\t\th1, h2 {margin: 0;padding: 2px 2px 0 2px; }\n"
             "\t\t\th1 {font-size: 24px; }\n"
             "\t\t\th2 {font-size: 18px; }\n"
             "\t\t\th3 {margin: 0 0 4px 0;font-size: 16px; }\n"
             "\t\t\th4 {font-size: 12px; }\n"
             "\t\t\th5 {font-size: 10px; }\n"
             "\t\t\ta {color: #666688;text-decoration: none; }\n"
             "\t\t\ta:hover, a:active {color: #333; }\n"
             "\t\t\tul, ol {padding-left: 20px; }\n"
             "\t\t\tul.float, ol.float {padding: 0;margin: 0; }\n"
             "\t\t\tul.float li, ol.float li {display: inline;float: left;padding-right: 6px;margin-right: 6px;list-style-type: none;border-right: 2px solid #eee; }\n"
             "\t\t\t.clear {clear: both; }\n"
             "\t\t\t.hide, .charts span {display: none; }\n"
             "\t\t\t.center {text-align: center; }\n"
             "\t\t\t.float {float: left; }\n"
             "\t\t\t.mt {margin-top: 20px; }\n"
             "\t\t\t.mb {margin-bottom: 20px; }\n"
             "\t\t\t.force-wrap {word-wrap: break-word; }\n"
             "\t\t\t.mono {font-family: \"Lucida Console\", Monaco, monospace;font-size: 12px; }\n"
             "\t\t\t.toggle {cursor: pointer; }\n"
             "\t\t\th2.toggle {padding-left: 16px;background: url() 0 -10px no-repeat; }\n"
             "\t\t\th2.open {margin-bottom: 10px;background-position: 0 9px; }\n"
             "\t\t\th3.toggle {padding-left: 16px;background: url() 0 -11px no-repeat; }\n"
             "\t\t\th3.open {background-position: 0 7px; }\n"
             "\t\t\th4.toggle {margin: 0 0 8px 0;padding-left: 12px;background: url() 0 -8px no-repeat; }\n"
             "\t\t\th4.open {background-position: 0 6px; }\n"
             "\t\t\ta.toggle-details {margin: 0 0 8px 0;padding-left: 12px;background: url() 0 4px no-repeat; }\n"
             "\t\t\ta.open {background-position: 0 -11px; }\n"
             "\t\t\ttd.small a.toggle-details {background-position: 0 2px; }\n"
             "\t\t\ttd.small a.open {background-position: 0 -13px; }\n"
             "\t\t\t#active-help, .help-box {display: none; }\n"
             "\t\t\t#active-help {position: absolute;width: 350px;padding: 3px;background: #fff;z-index: 10; }\n"
             "\t\t\t#active-help-dynamic {padding: 6px 6px 18px 6px;background: #eeeef5;outline: 1px solid #ddd;font-size: 13px; }\n"
             "\t\t\t#active-help .close {position: absolute;right: 10px;bottom: 4px; }\n"
             "\t\t\t.help-box h3 {margin: 0 0 5px 0;font-size: 16px; }\n"
             "\t\t\t.help-box {border: 1px solid #ccc;background-color: #fff;padding: 10px; }\n"
             "\t\t\ta.help {cursor: help; }\n"
             "\t\t\t.section {position: relative;width: 1150px;padding: 8px;margin-left: auto;margin-right: auto;margin-bottom: -1px;border: 1px solid #ccc;background-color: #fff;-moz-box-shadow: 4px 4px 4px #bbb;-webkit-box-shadow: 4px 4px 4px #bbb;box-shadow: 4px 4px 4px #bbb;text-align: left; }\n"
             "\t\t\t.section-open {margin-top: 25px;margin-bottom: 35px;-moz-border-radius: 15px;-khtml-border-radius: 15px;-webkit-border-radius: 15px;border-radius: 15px; }\n"
             "\t\t\t.grouped-first {-moz-border-radius-topright: 15px;-moz-border-radius-topleft: 15px;-khtml-border-top-right-radius: 15px;-khtml-border-top-left-radius: 15px;-webkit-border-top-right-radius: 15px;-webkit-border-top-left-radius: 15px;border-top-right-radius: 15px;border-top-left-radius: 15px; }\n"
             "\t\t\t.grouped-last {-moz-border-radius-bottomright: 15px;-moz-border-radius-bottomleft: 15px;-khtml-border-bottom-right-radius: 15px;-khtml-border-bottom-left-radius: 15px;-webkit-border-bottom-right-radius: 15px;-webkit-border-bottom-left-radius: 15px;border-bottom-right-radius: 15px;border-bottom-left-radius: 15px; }\n"
             "\t\t\t.section .toggle-content {padding: 0; }\n"
             "\t\t\t.player-section .toggle-content {padding-left: 16px;margin-bottom: 20px; }\n"
             "\t\t\t.subsection {background-color: #ccc;width: 1000px;padding: 8px;margin-bottom: 20px;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px;font-size: 12px; }\n"
             "\t\t\t.subsection-small {width: 500px; }\n"
             "\t\t\t.subsection h4 {margin: 0 0 10px 0; }\n"
             "\t\t\t.profile .subsection p {margin: 0; }\n"
             "\t\t\t#raid-summary .toggle-content {padding-bottom: 0px; }\n"
             "\t\t\tul.params {padding: 0;margin: 4px 0 0 6px; }\n"
             "\t\t\tul.params li {float: left;padding: 2px 10px 2px 10px;margin-left: 10px;list-style-type: none;background: #eeeef5;font-family: \"Lucida Grande\", Arial, sans-serif;font-size: 11px; }\n"
             "\t\t\t#masthead ul.params {margin-left: 4px; }\n"
             "\t\t\t#masthead ul.params li {margin-left: 0px;margin-right: 10px; }\n"
             "\t\t\t.player h2 {margin: 0; }\n"
             "\t\t\t.player ul.params {position: relative;top: 2px; }\n"
             "\t\t\t#masthead h2 {margin: 10px 0 5px 0; }\n"
             "\t\t\t#notice {border: 1px solid #ddbbbb;background: #ffdddd;font-size: 12px; }\n"
             "\t\t\t#notice h2 {margin-bottom: 10px; }\n"
             "\t\t\t.alert {width: 800px;padding: 10px;margin: 10px 0 10px 0;background-color: #ddd;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px; }\n"
             "\t\t\t.alert p {margin-bottom: 0px; }\n"
             "\t\t\t.section .toggle-content {padding-left: 18px; }\n"
             "\t\t\t.player > .toggle-content {padding-left: 0; }\n"
             "\t\t\t.toc {float: left;padding: 0; }\n"
             "\t\t\t.toc-wide {width: 560px; }\n"
             "\t\t\t.toc-narrow {width: 375px; }\n"
             "\t\t\t.toc li {margin-bottom: 10px;list-style-type: none; }\n"
             "\t\t\t.toc li ul {padding-left: 10px; }\n"
             "\t\t\t.toc li ul li {margin: 0;list-style-type: none;font-size: 13px; }\n"
             "\t\t\t.charts {float: left;width: 541px;margin-top: 10px; }\n"
             "\t\t\t.charts-left {margin-right: 40px; }\n"
             "\t\t\t.charts img {padding: 8px;margin: 0 auto;margin-bottom: 20px;border: 1px solid #ccc;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px;-moz-box-shadow: inset 1px 1px 4px #ccc;-webkit-box-shadow: inset 1px 1px 4px #ccc;box-shadow: inset 1px 1px 4px #ccc; }\n"
             "\t\t\t.talents div.float {width: auto;margin-right: 50px; }\n"
             "\t\t\ttable.sc {border: 0;background-color: #eee; }\n"
             "\t\t\ttable.sc tr {background-color: #fff; }\n"
             "\t\t\ttable.sc tr.head {background-color: #aaa;color: #fff; }\n"
             "\t\t\ttable.sc tr.odd {background-color: #f3f3f3; }\n"
             "\t\t\ttable.sc th {padding: 2px 4px 4px 4px;text-align: center;background-color: #aaa;color: #fcfcfc; }\n"
             "\t\t\ttable.sc th.small {padding: 2px 2px;font-size: 12px; }\n"
             "\t\t\ttable.sc th a {color: #fff;text-decoration: underline; }\n"
             "\t\t\ttable.sc th a:hover, table.sc th a:active {color: #f1f1ff; }\n"
             "\t\t\ttable.sc td {padding: 2px;text-align: center;font-size: 13px; }\n"
             "\t\t\ttable.sc th.left, table.sc td.left, table.sc tr.left th, table.sc tr.left td {text-align: left; }\n"
             "\t\t\ttable.sc th.right, table.sc td.right, table.sc tr.right th, table.sc tr.right td {text-align: right;padding-right: 4px; }\n"
             "\t\t\ttable.sc th.small {padding: 2px 2px 3px 2px;font-size: 11px; }\n"
             "\t\t\ttable.sc td.small {padding: 2px 2px 3px 2px;font-size: 11px; }\n"
             "\t\t\ttable.sc tr.details td {padding: 0 0 15px 15px;text-align: left;background-color: #fff;font-size: 11px; }\n"
             "\t\t\ttable.sc tr.details td ul {padding: 0;margin: 4px 0 8px 0; }\n"
             "\t\t\ttable.sc tr.details td ul li {clear: both;padding: 2px;list-style-type: none; }\n"
             "\t\t\ttable.sc tr.details td ul li span.label {display: block;padding: 2px;float: left;width: 145px;margin-right: 4px;background: #f3f3f3; }\n"
             "\t\t\ttable.sc tr.details td ul li span.tooltip {display: block;float: left;width: 190px; }\n"
             "\t\t\ttable.sc tr.details td ul li span.tooltip-wider {display: block;float: left;width: 350px; }\n"
             "\t\t\ttable.sc tr.details td div.float {width: 350px; }\n"
             "\t\t\ttable.sc tr.details td div.float h5 {margin-top: 4px; }\n"
             "\t\t\ttable.sc tr.details td div.float ul {margin: 0 0 12px 0; }\n"
             "\t\t\ttable.sc td.filler {background-color: #ccc; }\n"
             "\t\t\ttable.sc .dynamic-buffs tr.details td ul li span.label {width: 120px; }\n"
             "\t\t</style>\n" );
  }
  else
  {
    fprintf( file,
             "\t\t<style type=\"text/css\" media=\"all\">\n"
             "\t\t\t* {border: none;margin: 0;padding: 0; }\n"
             "\t\t\tbody {padding: 5px 25px 25px 25px;font-family: \"Lucida Grande\", Arial, sans-serif;font-size: 14px;background: #261307;color: #FFF;text-align: center; }\n"
             "\t\t\tp {margin: 1em 0 1em 0; }\n"
             "\t\t\th1, h2, h3, h4, h5, h6 {width: auto;color: #FDD017;margin-top: 1em;margin-bottom: 0.5em; }\n"
             "\t\t\th1, h2 {margin: 0;padding: 2px 2px 0 2px; }\n"
             "\t\t\th1 {font-size: 28px;text-shadow: 0 0 3px #FDD017; }\n"
             "\t\t\th2 {font-size: 18px; }\n"
             "\t\t\th3 {margin: 0 0 4px 0;font-size: 16px; }\n"
             "\t\t\th4 {font-size: 12px; }\n"
             "\t\t\th5 {font-size: 10px; }\n"
             "\t\t\ta {color: #FDD017;text-decoration: none; }\n"
             "\t\t\ta:hover, a:active {text-shadow: 0 0 1px #FDD017; }\n"
             "\t\t\tul, ol {padding-left: 20px; }\n"
             "\t\t\tul.float, ol.float {padding: 0;margin: 0; }\n"
             "\t\t\tul.float li, ol.float li {display: inline;float: left;padding-right: 6px;margin-right: 6px;list-style-type: none;border-right: 2px solid #333; }\n"
             "\t\t\t.clear {clear: both; }\n"
             "\t\t\t.hide, .charts span {display: none; }\n"
             "\t\t\t.center {text-align: center; }\n"
             "\t\t\t.float {float: left; }\n"
             "\t\t\t.mt {margin-top: 20px; }\n"
             "\t\t\t.mb {margin-bottom: 20px; }\n"
             "\t\t\t.force-wrap {word-wrap: break-word; }\n"
             "\t\t\t.mono {font-family: \"Lucida Console\", Monaco, monospace;font-size: 12px; }\n"
             "\t\t\t.toggle {cursor: pointer; }\n"
             "\t\t\th2.toggle {padding-left: 18px;background: url() 0 -10px no-repeat; }\n"
             "\t\t\th2.toggle:hover {text-shadow: 0 0 2px #FDD017; }\n"
             "\t\t\th2.open {margin-bottom: 10px;background-position: 0 9px; }\n"
             "\t\t\t#home-toc h2.open {margin-top: 20px; }\n"
             "\t\t\th3.toggle {padding-left: 16px;background: url() 0 -11px no-repeat; }\n"
             "\t\t\th3.toggle:hover {text-shadow: 0 0 2px #CDB007; }\n"
             "\t\t\th3.open {background-position: 0 7px; }\n"
             "\t\t\th4.toggle {margin: 0 0 8px 0;padding-left: 12px;background: url() 0 -8px no-repeat; }\n"
             "\t\t\th4.open {background-position: 0 6px; }\n"
             "\t\t\ta.toggle-details {margin: 0 0 8px 0;padding-left: 12px;background: url() 0 -9px no-repeat; }\n"
             "\t\t\ta.open {background-position: 0 6px; }\n"
             "\t\t\ttd.small a.toggle-details {background-position: 0 -10px; }\n"
             "\t\t\ttd.small a.open {background-position: 0 5px; }\n"
             "\t\t\t#active-help, .help-box {display: none;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px; }\n"
             "\t\t\t#active-help {position: absolute;width: auto;padding: 3px;background: transparent;z-index: 10; }\n"
             "\t\t\t#active-help-dynamic {max-width: 400px;padding: 8px 8px 20px 8px;background: #333;font-size: 13px;text-align: left;border: 1px solid #222;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px;-moz-box-shadow: 4px 4px 10px #000;-webkit-box-shadow: 4px 4px 10px #000;box-shadow: 4px 4px 10px #000; }\n"
             "\t\t\t#active-help .close {display: block;height: 14px;width: 14px;position: absolute;right: 12px;bottom: 7px;background: #000 url() no-repeat; }\n"
             "\t\t\t#active-help .close:hover {background-color: #1d1d1d; }\n"
             "\t\t\t.help-box h3 {margin: 0 0 12px 0;font-size: 14px;color: #C68E17; }\n"
             "\t\t\t.help-box p {margin: 0 0 10px 0; }\n"
             "\t\t\t.help-box {background-color: #000;padding: 10px; }\n"
             "\t\t\ta.help {color: #C68E17;cursor: help; }\n"
             "\t\t\ta.help:hover {text-shadow: 0 0 1px #C68E17; }\n"
             "\t\t\t.section {position: relative;width: 1150px;padding: 8px;margin-left: auto;margin-right: auto;margin-bottom: -1px;border: 0;-moz-box-shadow: 0px 0px 8px #FDD017;-webkit-box-shadow: 0px 0px 8px #FDD017;box-shadow: 0px 0px 8px #FDD017;color: #fff;background-color: #000;text-align: left; }\n"
             "\t\t\t.section-open {margin-top: 25px;margin-bottom: 35px;-moz-border-radius: 15px;-khtml-border-radius: 15px;-webkit-border-radius: 15px;border-radius: 15px; }\n"
             "\t\t\t.grouped-first {-moz-border-radius-topright: 15px;-moz-border-radius-topleft: 15px;-khtml-border-top-right-radius: 15px;-khtml-border-top-left-radius: 15px;-webkit-border-top-right-radius: 15px;-webkit-border-top-left-radius: 15px;border-top-right-radius: 15px;border-top-left-radius: 15px; }\n"
             "\t\t\t.grouped-last {-moz-border-radius-bottomright: 15px;-moz-border-radius-bottomleft: 15px;-khtml-border-bottom-right-radius: 15px;-khtml-border-bottom-left-radius: 15px;-webkit-border-bottom-right-radius: 15px;-webkit-border-bottom-left-radius: 15px;border-bottom-right-radius: 15px;border-bottom-left-radius: 15px; }\n"
             "\t\t\t.section .toggle-content {padding: 0; }\n"
             "\t\t\t.player-section .toggle-content {padding-left: 16px; }\n"
             "\t\t\t#home-toc .toggle-content {margin-bottom: 20px; }\n"
             "\t\t\t.subsection {background-color: #333;width: 1000px;padding: 8px;margin-bottom: 20px;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px;font-size: 12px; }\n"
             "\t\t\t.subsection-small {width: 500px; }\n"
             "\t\t\t.subsection h4 {margin: 0 0 10px 0;color: #fff; }\n"
             "\t\t\t.profile .subsection p {margin: 0; }\n"
             "\t\t\t#raid-summary .toggle-content {padding-bottom: 0px; }\n"
             "\t\t\tul.params {padding: 0;margin: 4px 0 0 6px; }\n"
             "\t\t\tul.params li {float: left;padding: 2px 10px 2px 10px;margin-left: 10px;list-style-type: none;background: #2f2f2f;color: #ddd;font-family: \"Lucida Grande\", Arial, sans-serif;font-size: 11px;-moz-border-radius: 8px;-khtml-border-radius: 8px;-webkit-border-radius: 8px;border-bottom-radius: 8px; }\n"
             "\t\t\tul.params li.linked:hover {background: #393939; }\n"
             "\t\t\tul.params li a {color: #ddd; }\n"
             "\t\t\tul.params li a:hover {text-shadow: none; }\n"
             "\t\t\t.player h2 {margin: 0; }\n"
             "\t\t\t.player ul.params {position: relative;top: 2px; }\n"
             "\t\t\t#masthead {height: auto;padding-bottom: 15px;border: 0;-moz-border-radius: 15px;-khtml-border-radius: 15px;-webkit-border-radius: 15px;border-radius: 15px;-moz-box-shadow: 0px 0px 8px #FDD017;-webkit-box-shadow: 0px 0px 8px #FDD017;box-shadow: 0px 0px 8px #FDD017;text-align: left;color: #FDD017;background: #000 url() 7px 13px no-repeat; }\n"
             "\t\t\t#masthead h1 {margin: 57px 0 0 355px; }\n"
             "\t\t\t#home #masthead h1 {margin-top: 98px; }\n"
             "\t\t\t#masthead h2 {margin-left: 355px; }\n"
             "\t\t\t#masthead ul.params {margin: 20px 0 0 345px; }\n"
             "\t\t\t#masthead p {color: #fff;margin: 20px 20px 0 20px; }\n"
             "\t\t\t#notice {font-size: 12px;-moz-box-shadow: 0px 0px 8px #E41B17;-webkit-box-shadow: 0px 0px 8px #E41B17;box-shadow: 0px 0px 8px #E41B17; }\n"
             "\t\t\t#notice h2 {margin-bottom: 10px; }\n"
             "\t\t\t.alert {width: 800px;padding: 10px;margin: 10px 0 10px 0;background-color: #333;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px;-moz-box-shadow: inset 0px 0px 6px #C11B17;-webkit-box-shadow: inset 0px 0px 6px #C11B17;box-shadow: inset 0px 0px 6px #C11B17; }\n"
             "\t\t\t.alert p {margin-bottom: 0px; }\n"
             "\t\t\t.section .toggle-content {padding-left: 18px; }\n"
             "\t\t\t.player > .toggle-content {padding-left: 0; }\n"
             "\t\t\t.toc {float: left;padding: 0; }\n"
             "\t\t\t.toc-wide {width: 560px; }\n"
             "\t\t\t.toc-narrow {width: 375px; }\n"
             "\t\t\t.toc li {margin-bottom: 10px;list-style-type: none; }\n"
             "\t\t\t.toc li ul {padding-left: 10px; }\n"
             "\t\t\t.toc li ul li {margin: 0;list-style-type: none;font-size: 13px; }\n"
             "\t\t\t.charts {float: left;width: 541px;margin-top: 10px; }\n"
             "\t\t\t.charts-left {margin-right: 40px; }\n"
             "\t\t\t.charts img {background-color: #333;padding: 5px;margin-bottom: 20px;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px; }\n"
             "\t\t\t.talents div.float {width: auto;margin-right: 50px; }\n"
             "\t\t\ttable.sc {background-color: #333;padding: 4px 2px 2px 2px;margin: 10px 0 20px 0;-moz-border-radius: 6px;-khtml-border-radius: 6px;-webkit-border-radius: 6px;border-radius: 6px; }\n"
             "\t\t\ttable.sc tr {color: #fff;background-color: #1a1a1a; }\n"
             "\t\t\ttable.sc tr.head {background-color: #aaa;color: #fff; }\n"
             "\t\t\ttable.sc tr.odd {background-color: #222; }\n"
             "\t\t\ttable.sc th {padding: 2px 4px 4px 4px;text-align: center;background-color: #333;color: #fff; }\n"
             "\t\t\ttable.sc td {padding: 2px;text-align: center;font-size: 13px; }\n"
             "\t\t\ttable.sc th.left, table.sc td.left, table.sc tr.left th, table.sc tr.left td {text-align: left; }\n"
             "\t\t\ttable.sc th.right, table.sc td.right, table.sc tr.right th, table.sc tr.right td {text-align: right;padding-right: 4px; }\n"
             "\t\t\ttable.sc th.small {padding: 2px 2px 3px 2px;font-size: 11px; }\n"
             "\t\t\ttable.sc td.small {padding: 2px 2px 3px 2px;font-size: 11px; }\n"
             "\t\t\ttable.sc tr.details td {padding: 0 0 15px 15px;text-align: left;background-color: #333;font-size: 11px; }\n"
             "\t\t\ttable.sc tr.details td ul {padding: 0;margin: 4px 0 8px 0; }\n"
             "\t\t\ttable.sc tr.details td ul li {clear: both;padding: 2px;list-style-type: none; }\n"
             "\t\t\ttable.sc tr.details td ul li span.label {display: block;padding: 2px;float: left;width: 145px;margin-right: 4px;background: #222; }\n"
             "\t\t\ttable.sc tr.details td ul li span.tooltip {display: block;float: left;width: 190px; }\n"
             "\t\t\ttable.sc tr.details td ul li span.tooltip-wider {display: block;float: left;width: 350px; }\n"
             "\t\t\ttable.sc tr.details td div.float {width: 350px; }\n"
             "\t\t\ttable.sc tr.details td div.float h5 {margin-top: 4px; }\n"
             "\t\t\ttable.sc tr.details td div.float ul {margin: 0 0 12px 0; }\n"
             "\t\t\ttable.sc td.filler {background-color: #333; }\n"
             "\t\t\ttable.sc .dynamic-buffs tr.details td ul li span.label {width: 120px; }\n"
             "\t\t\ttr.details td table.details {padding: 0px;margin: 5px 0 10px 0; }\n"
             "\t\t\ttr.details td table.details tr th {background-color: #222; }\n"
             "\t\t\ttr.details td table.details tr td {background-color: #2d2d2d; }\n"
             "\t\t\ttr.details td table.details tr.odd td {background-color: #292929; }\n"
             "\t\t\ttr.details td table.details tr td {padding: 1px 3px 1px 3px; }\n"
             "\t\t\ttr.details td table.details tr td.right {text-align: right; }\n"
             "\t\t\t.player-thumbnail {float: right;margin: 8px;border-radius: 12px;-moz-border-radius: 12px;-webkit-border-radius: 12px;-khtml-border-radius: 12px; }\n"
             "\t\t</style>\n" );
  }
}

// print_html_masthead ====================================================

static void print_html_masthead( FILE*  file, sim_t* sim )
{
  // Begin masthead section
  fprintf( file,
           "\t\t<div id=\"masthead\" class=\"section section-open\">\n\n" );

  fprintf( file,
           "\t\t\t<h1><a href=\"http://code.google.com/p/simulationcraft/\">SimulationCraft %s-%s</a></h1>\n"
           "\t\t\t<h2>for World of Warcraft %s %s (build level %s)</h2>\n\n",
           SC_MAJOR_VERSION, SC_MINOR_VERSION, dbc_t::wow_version( sim -> dbc.ptr ), ( sim -> dbc.ptr ? "PTR" : "Live" ), dbc_t::build_level( sim -> dbc.ptr ) );

  time_t rawtime;
  time ( &rawtime );

  fprintf( file,
           "\t\t\t<ul class=\"params\">\n" );
  fprintf( file,
           "\t\t\t\t<li><b>Timestamp:</b> %s</li>\n",
           ctime( &rawtime ) );
  fprintf( file,
           "\t\t\t\t<li><b>Iterations:</b> %d</li>\n",
           sim -> iterations );

  if ( sim -> vary_combat_length > 0.0 )
  {
    timespan_t min_length = sim -> max_time * ( 1 - sim -> vary_combat_length );
    timespan_t max_length = sim -> max_time * ( 1 + sim -> vary_combat_length );
    fprintf( file,
             "\t\t\t\t<li class=\"linked\"><a href=\"#help-fight-length\" class=\"help\"><b>Fight Length:</b> %.0f - %.0f</a></li>\n",
             min_length.total_seconds(),
             max_length.total_seconds() );
  }
  else
  {
    fprintf( file,
             "\t\t\t\t<li><b>Fight Length:</b> %.0f</li>\n",
             sim -> max_time.total_seconds() );
  }
  fprintf( file,
           "\t\t\t\t<li><b>Fight Style:</b> %s</li>\n",
           sim -> fight_style.c_str() );
  fprintf( file,
           "\t\t\t</ul>\n" );
  fprintf( file,
           "\t\t\t<div class=\"clear\"></div>\n\n"
           "\t\t</div>\n\n" );
  // End masthead section
}

} // ANONYMOUS NAMESPACE ====================================================

// report_t::print_html =====================================================
void report_t::print_html( sim_t* sim )
{
  int num_players = ( int ) sim -> players_by_name.size();

  if ( num_players == 0 ) return;
  if ( sim -> simulation_length.mean == 0 ) return;
  if ( sim -> html_file_str.empty() ) return;

  FILE* file = fopen( sim -> html_file_str.c_str(), "w" );
  if ( ! file )
  {
    sim -> errorf( "Unable to open html file '%s'\n", sim -> html_file_str.c_str() );
    return;
  }

  fprintf( file,
           "<!DOCTYPE html>\n\n" );
  fprintf( file,
           "<html>\n\n" );

  fprintf( file,
           "\t<head>\n\n" );
  fprintf( file,
           "\t\t<title>Simulationcraft Results</title>\n\n" );
  fprintf( file,
           "\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\n" );

  print_html_styles( file, sim );

  fprintf( file,
           "\t</head>\n\n" );

  fprintf( file,
           "\t<body>\n\n" );

  if ( ! sim -> error_list.empty() )
  {
    fprintf( file,
             "\t\t<pre>\n" );
    size_t num_errors = sim -> error_list.size();
    for ( size_t i=0; i < num_errors; i++ )
      fprintf( file,
               "      %s\n", sim -> error_list[ i ].c_str() );
    fprintf( file,
             "\t\t</pre>\n\n" );
  }

  // Prints div wrappers for help popups
  fprintf( file,
           "\t\t<div id=\"active-help\">\n"
           "\t\t\t<div id=\"active-help-dynamic\">\n"
           "\t\t\t\t<div class=\"help-box\"></div>\n"
           "\t\t\t\t<a href=\"#\" class=\"close\"><span class=\"hide\">close</span></a>\n"
           "\t\t\t</div>\n"
           "\t\t</div>\n\n" );

  print_html_masthead( file, sim );

#if SC_BETA
  fprintf( file,
           "\t\t<div id=\"notice\" class=\"section section-open\">\n" );
  fprintf( file,
           "\t\t\t<h2>Beta Release</h2>\n" );
  int ii = 0;
  if ( beta_warnings[ 0 ] )
    fprintf( file,
             "\t\t\t<ul>\n" );
  while ( beta_warnings[ ii ] )
  {
    fprintf( file,
             "\t\t\t\t<li>%s</li>\n",
             beta_warnings[ ii ] );
    ii++;
  }
  if ( beta_warnings[ 0 ] )
    fprintf( file,
             "\t\t\t</ul>\n" );
  fprintf( file,
           "\t\t</div>\n\n" );
#endif

  if ( num_players > 1 )
  {
    print_html_contents( file, sim );
  }

  if ( num_players > 1 )
  {
    print_html_raid_summary( file, sim );
    print_html_scale_factors( file, sim );
  }

  // Players
  for ( int i=0; i < num_players; i++ )
  {
    report_t::print_html_player( file, sim -> players_by_name[ i ], i );

    // Pets
    if ( sim -> report_pets_separately )
    {
      for ( pet_t* pet = sim -> players_by_name[ i ] -> pet_list; pet; pet = pet -> next_pet )
      {
        if ( pet -> summoned )
          report_t::print_html_player( file, pet, 1 );
      }
    }
  }

  // Sim Summary
  print_html_sim_summary( file, sim );

  // Report Targets
  if ( sim -> report_targets )
  {
    for ( int i=0; i < ( int ) sim -> targets_by_name.size(); i++ )
    {
      report_t::print_html_player( file, sim -> targets_by_name[ i ], i );

      // Pets
      if ( sim -> report_pets_separately )
      {
        for ( pet_t* pet = sim -> targets_by_name[ i ] -> pet_list; pet; pet = pet -> next_pet )
        {
          //if ( pet -> summoned )
          report_t::print_html_player( file, pet, 1 );
        }
      }
    }
  }

  // Help Boxes
  print_html_help_boxes( file, sim );

  // jQuery
  fprintf ( file,
            "\t\t<script type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js\"></script>\n" );

  // Toggles, image load-on-demand, etc. Load from simulationcraft.org if
  // hosted_html=1, otherwise embed
  if ( sim -> hosted_html )
  {
    fprintf( file,
             "\t\t<script type=\"text/javascript\" src=\"http://www.simulationcraft.org/js/ga.js\"></script>\n"
             "\t\t<script type=\"text/javascript\" src=\"http://www.simulationcraft.org/js/rep.js\"></script>\n"
             "\t\t<script type=\"text/javascript\" src=\"http://static.wowhead.com/widgets/power.js\"></script>\n" );
  }
  else
  {
    fprintf( file,
             "\t\t<script type=\"text/javascript\">\n"
             "\t\t\tfunction load_images(containers) {\n"
             "\t\t\t\tvar $j = jQuery.noConflict();\n"
             "\t\t\t\tcontainers.each(function() {\n"
             "\t\t\t\t\t$j(this).children('span').each(function() {\n"
             "\t\t\t\t\t\tvar j = jQuery.noConflict();\n"
             "\t\t\t\t\t\timg_class = $j(this).attr('class');\n"
             "\t\t\t\t\t\timg_alt = $j(this).attr('title');\n"
             "\t\t\t\t\t\timg_src = $j(this).html().replace(/&amp;/g, '&');\n"
             "\t\t\t\t\t\tvar img = new Image();\n"
             "\t\t\t\t\t\t$j(img).attr('class', img_class);\n"
             "\t\t\t\t\t\t$j(img).attr('src', img_src);\n"
             "\t\t\t\t\t\t$j(img).attr('alt', img_alt);\n"
             "\t\t\t\t\t\t$j(this).replaceWith(img);\n"
             "\t\t\t\t\t\t$j(this).load();\n"
             "\t\t\t\t\t});\n"
             "\t\t\t\t});\n"
             "\t\t\t}\n"
             "\t\t\tfunction open_anchor(anchor) {\n"
             "\t\t\t\tvar img_id = '';\n"
             "\t\t\t\tvar src = '';\n"
             "\t\t\t\tvar target = '';\n"
             "\t\t\t\tanchor.addClass('open');\n"
             "\t\t\t\tvar section = anchor.parent('.section');\n"
             "\t\t\t\tsection.addClass('section-open');\n"
             "\t\t\t\tsection.removeClass('grouped-first');\n"
             "\t\t\t\tsection.removeClass('grouped-last');\n"
             "\t\t\t\tif (!(section.next().hasClass('section-open'))) {\n"
             "\t\t\t\t\tsection.next().addClass('grouped-first');\n"
             "\t\t\t\t}\n"
             "\t\t\t\tif (!(section.prev().hasClass('section-open'))) {\n"
             "\t\t\t\t\tsection.prev().addClass('grouped-last');\n"
             "\t\t\t\t}\n"
             "\t\t\t\tanchor.next('.toggle-content').show(150);\n"
             "\t\t\t\tchart_containers = anchor.next('.toggle-content').find('.charts');\n"
             "\t\t\t\tload_images(chart_containers);\n"
             "\t\t\t\tsetTimeout(\"var ypos=0;var e=document.getElementById('\" + section.attr('id') + \"');while( e != null ) {ypos += e.offsetTop;e = e.offsetParent;}window.scrollTo(0,ypos);\", 500);\n"
             "\t\t\t}\n"
             "\t\t\tjQuery.noConflict();\n"
             "\t\t\tjQuery(document).ready(function($) {\n"
             "\t\t\t\tvar chart_containers = false;\n"
             "\t\t\t\tvar anchor_check = document.location.href.split('#');\n"
             "\t\t\t\tif (anchor_check.length > 1) {\n"
             "\t\t\t\t\tvar anchor = anchor_check[anchor_check.length - 1];\n"
             "\t\t\t\t}\n"
             "\t\t\t\t$('a.ext').mouseover(function() {\n"
             "\t\t\t\t\t$(this).attr('target', '_blank');\n"
             "\t\t\t\t});\n"
             "\t\t\t\t$('.toggle').click(function(e) {\n"
             "\t\t\t\t\tvar img_id = '';\n"
             "\t\t\t\t\tvar src = '';\n"
             "\t\t\t\t\tvar target = '';\n"
             "\t\t\t\t\te.preventDefault();\n"
             "\t\t\t\t\t$(this).toggleClass('open');\n"
             "\t\t\t\t\tvar section = $(this).parent('.section');\n"
             "\t\t\t\t\tif (section.attr('id') != 'masthead') {\n"
             "\t\t\t\t\t\tsection.toggleClass('section-open');\n"
             "\t\t\t\t\t}\n"
             "\t\t\t\t\tif (section.attr('id') != 'masthead' && section.hasClass('section-open')) {\n"
             "\t\t\t\t\t\tsection.removeClass('grouped-first');\n"
             "\t\t\t\t\t\tsection.removeClass('grouped-last');\n"
             "\t\t\t\t\t\tif (!(section.next().hasClass('section-open'))) {\n"
             "\t\t\t\t\t\t\tsection.next().addClass('grouped-first');\n"
             "\t\t\t\t\t\t}\n"
             "\t\t\t\t\t\tif (!(section.prev().hasClass('section-open'))) {\n"
             "\t\t\t\t\t\t\tsection.prev().addClass('grouped-last');\n"
             "\t\t\t\t\t\t}\n"
             "\t\t\t\t\t} else if (section.attr('id') != 'masthead') {\n"
             "\t\t\t\t\t\tif (section.hasClass('final') || section.next().hasClass('section-open')) {\n"
             "\t\t\t\t\t\t\tsection.addClass('grouped-last');\n"
             "\t\t\t\t\t\t} else {\n"
             "\t\t\t\t\t\t\tsection.next().removeClass('grouped-first');\n"
             "\t\t\t\t\t\t}\n"
             "\t\t\t\t\t\tif (section.prev().hasClass('section-open')) {\n"
             "\t\t\t\t\t\t\tsection.addClass('grouped-first');\n"
             "\t\t\t\t\t\t} else {\n"
             "\t\t\t\t\t\t\tsection.prev().removeClass('grouped-last');\n"
             "\t\t\t\t\t\t}\n"
             "\t\t\t\t\t}\n"
             "\t\t\t\t\t$(this).next('.toggle-content').toggle(150);\n"
             "\t\t\t\t\t$(this).prev('.toggle-thumbnail').toggleClass('hide');\n"
             "\t\t\t\t\tchart_containers = $(this).next('.toggle-content').find('.charts');\n"
             "\t\t\t\t\tload_images(chart_containers);\n"
             "\t\t\t\t});\n"
             "\t\t\t\t$('.toggle-details').click(function(e) {\n"
             "\t\t\t\t\te.preventDefault();\n"
             "\t\t\t\t\t$(this).toggleClass('open');\n"
             "\t\t\t\t\t$(this).parents().next('.details').toggleClass('hide');\n"
             "\t\t\t\t});\n"
             "\t\t\t\t$('.toggle-db-details').click(function(e) {\n"
             "\t\t\t\t\te.preventDefault();\n"
             "\t\t\t\t\t$(this).toggleClass('open');\n"
             "\t\t\t\t\t$(this).parent().next('.toggle-content').toggle(150);\n"
             "\t\t\t\t});\n"
             "\t\t\t\t$('.help').click(function(e) {\n"
             "\t\t\t\t\te.preventDefault();\n"
             "\t\t\t\t\tvar target = $(this).attr('href') + ' .help-box';\n"
             "\t\t\t\t\tvar content = $(target).html();\n"
             "\t\t\t\t\t$('#active-help-dynamic .help-box').html(content);\n"
             "\t\t\t\t\t$('#active-help .help-box').show();\n"
             "\t\t\t\t\tvar t = e.pageY - 20;\n"
             "\t\t\t\t\tvar l = e.pageX - 20;\n"
             "\t\t\t\t\t$('#active-help').css({top:t,left:l});\n"
             "\t\t\t\t\t$('#active-help').show(250);\n"
             "\t\t\t\t});\n"
             "\t\t\t\t$('#active-help a.close').click(function(e) {\n"
             "\t\t\t\t\te.preventDefault();\n"
             "\t\t\t\t\t$('#active-help').toggle(250);\n"
             "\t\t\t\t});\n"
             "\t\t\t\tif (anchor) {\n"
             "\t\t\t\t\tanchor = '#' + anchor;\n"
             "\t\t\t\t\ttarget = $(anchor).children('h2:first');\n"
             "\t\t\t\t\topen_anchor(target);\n"
             "\t\t\t\t}\n"
             "\t\t\t\t$('ul.toc li a').click(function(e) {\n"
             "\t\t\t\t\tanchor = $(this).attr('href');\n"
             "\t\t\t\t\ttarget = $(anchor).children('h2:first');\n"
             "\t\t\t\t\topen_anchor(target);\n"
             "\t\t\t\t});\n"
             "\t\t\t});\n"
             "\t\t</script>\n\n" );
  }

  if ( num_players > 1 ) print_html_raid_imagemaps( file, sim );

  fprintf( file,
           "\t</body>\n\n"
           "</html>\n" );

  fclose( file );
}
